package proxy;

import java.nio.ByteBuffer;
import com.Communicator;
import core.Config;
import core.Worker;
import interfaces.*;

/**
 * Classe responsavel por processar as mensagens recebidas pelo channel do Worker
 * 
 * @author robertow
 * 
 */
public class WorkerProxy extends Thread implements IWorkerProxy, IProxy{
	
	// Canal de comunicação do procurador do trabalhador
	private ICommunicator workerProxyChannel;
	
	// Canal de comunicação com o gerente o trabalhador
	private ICommunicator managerChannelSend;
	
	// Define um trabalhador
	private Worker worker;
	
	// Procurador do trabalhador
	static WorkerProxy workerProxy;
	
	// Descrição do canal de comunicação do procurador do trabalhador
	private String workerProxyChannelDesc;
	
	// Identificação do procurador do trabalhador
	private String workerProxyId;
	
	private String deafultIP;
	
	private boolean running = true;
	
	// Identificação do trabalhador
	private String workerId;
	
	// Identificação da tarefa
	private String jobId;
	
	// Tamanho da mensagem
	private int size;
	private int descSize;
	
	// Descrição da tarefa
	private byte[] jobDesc;
	
	// Tipo da mensagem
	private short msg_type;

	public static void main(String[] args) {
		String id = args[0];
		String defaultIP = args[1]; 
		String launcherChannelDesc = args[2];

		if (args.length != 3) {
			System.out.println("WorkerProxy => ");
			System.out.println("\t Faltam argumentos (ID_Worker ChannelManager \n");
			System.exit(1);
		}

		workerProxy = new WorkerProxy(id, defaultIP);

		try {
			ICommunicator launcherChannelSend = new Communicator();
			launcherChannelSend.connectServer(launcherChannelDesc);
			launcherChannelSend.sendMsgNodeStarted(launcherChannelSend.getSocket(), id, workerProxy.getChannelDesc());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public WorkerProxy(String workerProxyId, String defaultIP) {
		try {
			this.workerProxyId = workerProxyId;
			
			this.deafultIP = defaultIP;
			
			this.workerProxyChannel = new Communicator(this.deafultIP);
			this.workerProxyChannelDesc = this.workerProxyChannel.serverChannelDescription();
			this.worker = new Worker(this.workerProxyId, this);
			
			System.out.println("WorkerProxy Iniciado =>");
			System.out.println("\t Novo worker criado seu ID eh: " + this.workerProxyId);
			System.out.println("\t\t Seu channel eh: " + this.getChannelDesc() + "\n");

			this.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void run() {
		try {
			ByteBuffer buf = null;
			
			/////////////////////////////////////////////////////////////////////////
			System.out.println("WorkerProxy =>");
			System.out.println("\t Recebendo Mensagens ... \n");
			/////////////////////////////////////////////////////////////////////////
			
			while (this.running) {
				buf = workerProxyChannel.receiveMessages();
				msg_type = buf.getShort();
				size = buf.getInt();
				switch (msg_type) {
					case Config.NEW_JOB:
						jobId = Communicator.readString(buf).trim();
						descSize = size - 2 - 4 - (jobId.length() + 1);
						jobDesc = new byte[descSize];
						buf.get(jobDesc);
						worker.newJob(jobId, jobDesc);
					break;
					
					case Config.BOSS_CONTACT:
						workerId = Communicator.readString(buf).trim();
						worker.bossContact(workerId);
					break;
					
					default:
						System.out.println("WorkerProxy =>");
						System.out.println("\t\t LOST MESSAGE! Type: " + msg_type + "\n");
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void managerConnect(String channelDesc) {
		// TODO Auto-generated method stub
		try {
			this.managerChannelSend = new Communicator();
			this.managerChannelSend.connectServer(channelDesc);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void statusSend(String workerId, float capacity, int workload, long updateDate) {
		// TODO Auto-generated method stub
		try {
			this.managerChannelSend.sendMsgNodeStatus(this.managerChannelSend.getSocket(), workerId, capacity, workload, updateDate);
			// //////////////////////////////////////////////////////////////////////
			// System.out.println("Worker (" + this.workerId + ") =>");
			// System.out.println("\t Enviar NODE_STATUS: ");
			// System.out.println("\t\t CAPACIDADE: " + this.getCapacity());
			// System.out.println("\t\t WORKLOAD: " + this.getWorkload() + "\n");
			// //////////////////////////////////////////////////////////////////////
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void resultSend(String workerId, String jobId, byte[] jobResultDesc) {
		// TODO Auto-generated method stub
		try {
			this.managerChannelSend.sendMsgJobResult(this.managerChannelSend.getSocket(), workerId, jobId, jobResultDesc);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void setChannelDesc(String channelDesc) {
		// TODO Auto-generated method stub
		this.workerProxyChannelDesc = channelDesc;
	}

	@Override
	public String getChannelDesc() {
		// TODO Auto-generated method stub
		return this.workerProxyChannelDesc;
	}

	@Override
	public void setChannel(ICommunicator channel) {
		// TODO Auto-generated method stub
		this.workerProxyChannel = channel;
	}

	@Override
	public ICommunicator getChannel() {
		// TODO Auto-generated method stub
		return this.workerProxyChannel;
	}
}